home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
forms
/
FORMS
/
browser.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
19KB
|
608 lines
/*
* browser.c
*
* Forms Object class: BROWSER
*
* Written by: Mark Overmars
*
* Version 2.2 a
* Date: Jan 25, 1993
*/
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include "forms.h"
#define NL 10
/* Object specific information */
typedef struct {
int selected; /* Whether selected */
char txt[FL_BROWSER_LINELENGTH]; /* The text */
} LINE;
typedef struct {
LINE *text[FL_BROWSER_MAXLINE+1];/* The lines of text (line 0 is not used) */
int topline; /* Current topline */
int lines; /* Number of lines */
int selectline; /* Last selected line */
float fontsize; /* The character size */
int fontstyle; /* Style of font */
char specialkey; /* Key that indicates a special symbol */
} SPEC;
/***************** DATA STRUCTURE MAINTENANCE ************************/
static void delete_line(FL_OBJECT *ob, int linenumb)
/* Deletes a line from the browser */
{
SPEC *sp = ((SPEC *)(ob->spec));
LINE *ttt;
int i;
ttt = sp->text[linenumb];
for (i=linenumb; i<sp->lines; i++) sp->text[i] = sp->text[i+1];
sp->text[sp->lines] = ttt;
sp->lines--;
if (sp->selectline == linenumb) sp->selectline = 0;
else if (sp->selectline > linenumb) sp->selectline--;
}
static void insert_line(FL_OBJECT *ob, int linenumb, const char *newtext)
/* Inserts a line of text to a browser */
{
SPEC *sp = ((SPEC *)(ob->spec));
LINE *ttt;
int i;
if (sp->lines == FL_BROWSER_MAXLINE)
{
delete_line(ob,0);
linenumb--;
}
sp->lines++;
/* Create new line if required */
if (sp->text[sp->lines] == NULL)
sp->text[sp->lines] = (LINE *) fl_malloc(sizeof(LINE));
/* Shift lines */
ttt = sp->text[sp->lines];
for (i=sp->lines-1; i>=linenumb; i--) sp->text[i+1] = sp->text[i];
sp->text[linenumb] = ttt;
/* Fill in line */
sp->text[linenumb]->selected = 0;
strncpy(sp->text[linenumb]->txt,newtext,FL_BROWSER_LINELENGTH);
sp->text[linenumb]->txt[FL_BROWSER_LINELENGTH-1] = NULL;
if (sp->selectline >= linenumb) sp->selectline++;
}
static void replace_line(FL_OBJECT *ob, int linenumb, const char *newtext)
/* Replaces a line of text in a browser */
{
SPEC *sp = ((SPEC *)(ob->spec));
/* Fill in line */
strncpy(sp->text[linenumb]->txt,newtext,FL_BROWSER_LINELENGTH);
sp->text[linenumb]->txt[FL_BROWSER_LINELENGTH-1] = NULL;
}
/******************************** DRAWING ********************************/
static int partial = 0; /* Whether the next redraw should be partial.*/
/* 0 = not, 1 = no back, 2 = no back, slider.*/
static void calc_textarea(FL_OBJECT *ob, float *xx, float *yy,
float *ww, float *hh, int *screenlines)
/* Calculates the area in which the text is drawn */
{
SPEC *sp = ((SPEC *)(ob->spec));
float charheight = fl_get_char_height(sp->fontsize, sp->fontstyle);
/* character height */
*xx = ob->x + 1.5*FL_BROWSER_BW;
*yy = ob->y + 1.0*FL_BROWSER_BW;
*ww = ob->w - 3.0*FL_BROWSER_BW;
*hh = ob->h - 2.0*FL_BROWSER_BW;
*screenlines = (int) (*hh / charheight);
/* Check whether a slider will be shown */
if (sp->lines > *screenlines)
{ *xx += 7.0*FL_BROWSER_BW; *ww -= 7.0*FL_BROWSER_BW;}
}
static void correct_topline(FL_OBJECT *ob)
/* Corrects the position of the topline inside the browser */
{
SPEC *sp = ((SPEC *)(ob->spec));
int screenlines; /* lines on screen */
float xx,yy,ww,hh; /* text box */
calc_textarea(ob,&xx,&yy,&ww,&hh,&screenlines);
if (sp->lines > screenlines)
{
if (sp->lines - sp->topline + 1 < screenlines)
sp->topline = sp->lines - screenlines + 1;
if (sp->topline < 1) sp->topline = 1;
}
else
sp->topline = 1;
}
static void draw_textline(FL_OBJECT *ob, int line, float xx, float yy, float ww,
int back)
/* Draws the line on the browser at postion xx,yy, with maximal width ww.
back indicates whether the background should be drawn */
{
SPEC *sp = ((SPEC *)(ob->spec));
char *str; /* Start of actual string */
int style = sp->fontstyle; /* Actual font style used */
float size = sp->fontsize; /* Actual font size used */
int lcol = ob->lcol; /* Actual font color used */
int align = FL_ALIGN_LEFT; /* Actual alignment used */
float charheight = fl_get_char_height(size, style);
/* Draw the selection box if required */
if (line <= sp->lines && sp->text[line]->selected)
fl_rect(xx,yy-0.6*charheight,ww,charheight,ob->col2);
else if (back)
fl_rect(xx,yy-0.6*charheight,ww,charheight,ob->col1);
if (line > sp->lines) return;
/* Check for special lines */
str = sp->text[line]->txt;
while (str[0] != '\0' && str[0] == sp->specialkey)
{
switch (str[1]) {
case 'l': size = FL_LARGE_FONT;yy -= 5.0; break;
case 's': size = FL_SMALL_FONT; break;
case 'b': style = FL_BOLD_STYLE; break;
case 'i': style = FL_ITALIC_STYLE; break;
case 'f': style = FL_FIXED_STYLE; break;
case 'c': align = FL_ALIGN_CENTER; break;
case 'r': align = FL_ALIGN_RIGHT; break;
case 'C':
lcol = 0;
while (str[2] >= '0' && str[2] <= '9')
{lcol = 10* lcol + str[2] - '0'; str++;}
break;
case '_': /* line under it */
fl_line(xx,yy-0.6*charheight,ww,1.0,BLACK);
break;
}
str++; str++;
}
/* Draw the string */
fl_drw_text_cursor(align,xx,yy,ww,0.0,lcol,size,style,str,0,-1);
}
static void draw_browslider(FL_OBJECT *ob, int screenlines)
/* Draws the slider if required. */
{
SPEC *sp = ((SPEC *)(ob->spec));
float slsize, slpos; /* slider size and position */
slsize = (1.0*screenlines) / sp->lines;
slpos = 1.0 - (1.0*sp->topline -1.0) / (sp->lines - screenlines);
fl_drw_slider(ob->boxtype, ob->x,ob->y,7.0*FL_BROWSER_BW,ob->h,
FL_BROWSER_SLCOL,FL_BROWSER_SLCOL,FL_VERT_SLIDER,
slsize,slpos,"");
}
static void draw_browser(FL_OBJECT *ob)
/* Draws the browser */
{
SPEC *sp = ((SPEC *)(ob->spec));
float charheight = fl_get_char_height(sp->fontsize, sp->fontstyle);
/* character height */
int screenlines; /* lines on screen */
int i; /* counters, etc. */
float xx,yy,ww,hh; /* text box */
calc_textarea(ob,&xx,&yy,&ww,&hh,&screenlines);
correct_topline(ob);
if (sp->lines > screenlines)
{
draw_browslider(ob,screenlines);
fl_drw_box(ob->boxtype,ob->x+7.0*FL_BROWSER_BW,ob->y,
ob->w-7.0*FL_BROWSER_BW,ob->h, ob->col1,FL_BROWSER_BW);
}
else
{
fl_drw_box(ob->boxtype,ob->x,ob->y,ob->w,ob->h,ob->col1,FL_BROWSER_BW);
}
fl_drw_text_beside(ob->align,ob->x,ob->y,ob->w,ob->h,
ob->lcol,ob->lsize,ob->lstyle,ob->label);
fl_set_clipping(xx,yy,ww,hh-1.0);
for (i=screenlines-1; i >= 0 ; i--)
draw_textline(ob,i+sp->topline,xx,yy+hh-(i+0.5)*charheight,ww,FALSE);
fl_unset_clipping();
}
static void draw_browser_partial(FL_OBJECT *ob, int slid)
/* Draws the contents of the browser only. slid indicated whether the
slider should be redrawn. */
{
SPEC *sp = ((SPEC *)(ob->spec));
float charheight; /* character height */
int screenlines; /* lines on screen */
int i; /* counters, etc. */
float xx,yy,ww,hh; /* text box */
charheight = fl_get_char_height(sp->fontsize, sp->fontstyle);
calc_textarea(ob,&xx,&yy,&ww,&hh,&screenlines);
correct_topline(ob);
if (slid && sp->lines > screenlines) draw_browslider(ob,screenlines);
fl_set_clipping(xx,yy,ww,hh-1.);
for (i=screenlines-1; i >= 0 ; i--)
draw_textline(ob,i+sp->topline,xx,yy+hh-(i+0.5)*charheight,ww,TRUE);
fl_unset_clipping();
}
/***************** HANDLING EVENTS **************************/
#define NOEVENT 0
#define SELECTEVENT 1
#define DESELECTEVENT 2
#define SLIDEREVENT 3
#define PAGEEVENT 4
static int eventtype = NOEVENT; /* Type of interaction taking place */
static int pagesize; /* Amount to scroll for page events */
static int timdel; /* Time passes since last page change */
static int handle_mouse(FL_OBJECT *ob, float mx, float my)
/* handles a mouse change. returns whether a selection change has occured */
{
SPEC *sp = ((SPEC *)(ob->spec));
float charheight = fl_get_char_height(sp->fontsize, sp->fontstyle);
/* character height */
int screenlines; /* lines on screen */
float slsize,slpos,slval; /* slider size,pos and value */
int line; /* new number of lines */
int oldtopline = sp->topline; /* old value of topline */
int newtopline; /* New topline */
int slaction; /* Type of slider action */
/* Check whether ther are any lines */
if (sp->lines == 0) return FALSE;
/* Compute possible slider position change */
correct_topline(ob);
screenlines = (int) ((ob->h - 2.0*FL_BROWSER_BW) / charheight);
if (sp->lines > screenlines)
{
slsize = (1.0*screenlines) / sp->lines;
slpos = 1.0 - (1.0*sp->topline -1.0) / (sp->lines - screenlines);
slaction = fl_get_pos_in_slider(ob->x,ob->y,ob->w,ob->h,
FL_VERT_SLIDER,slsize,mx,my, slpos,&slval);
newtopline = (int) ((1.0-slval)*(sp->lines - screenlines) + 1.0);
}
/* Determine the type of event */
if (eventtype == NOEVENT)
{
if (sp->lines > screenlines && mx < ob->x+7.0*FL_BROWSER_BW)
{
if (slaction == 0)
eventtype = SLIDEREVENT;
else
{
eventtype =PAGEEVENT;
timdel = 0;
if (slaction == -2) pagesize = screenlines;
else if (slaction == -1) pagesize = 1;
else if (slaction == 1) pagesize = -1;
else if (slaction == 2) pagesize = -screenlines;
}
}
else
{
eventtype = SELECTEVENT;
line = sp->topline - (int) ((my-(ob->y+ob->h-FL_BROWSER_BW))/charheight);
if (ob->type == FL_MULTI_BROWSER &&
line >= 1 && line <= sp->lines && line < sp->topline+screenlines &&
sp->text[line]->selected)
eventtype = DESELECTEVENT;
}
}
/* Handle the event */
switch (eventtype) {
case PAGEEVENT:
if ((timdel++ % 30) == 0)
{
sp->topline += pagesize;
correct_topline(ob);
if (sp->topline == oldtopline) return 0;
partial = 1; fl_redraw_object(ob);
}
return 0;
case SLIDEREVENT:
sp->topline = newtopline;
correct_topline(ob);
if (sp->topline == oldtopline) return 0;
partial = 1; fl_redraw_object(ob);
return 0;
default:
if (ob->type == FL_NORMAL_BROWSER) return 0;
line = sp->topline - (int)((my-(ob->y+ob->h-FL_BROWSER_BW))/charheight);
if (line<sp->topline) line = sp->topline;
if (line>=sp->topline+screenlines) line = sp->topline+screenlines-1;
if (line>sp->lines) line = sp->lines;
if (eventtype == SELECTEVENT)
{
if (sp->text[line]->selected) return (ob->type != FL_MULTI_BROWSER);
if (ob->type != FL_MULTI_BROWSER && sp->selectline > 0)
sp->text[sp->selectline]->selected = 0;
sp->text[line]->selected = 1;
sp->selectline = line;
}
else /* eventtype == DESELECTEVENT && ob->type == FL_MULTI_BROWSER */
{
if (! sp->text[line]->selected) return 0;
sp->text[line]->selected = 0;
sp->selectline = -line;
}
partial = 2; fl_redraw_object(ob);
return 1;
}
}
/*-----------------------------------------------*/
static int statuschanged = 0;
static int handle_browser(FL_OBJECT *ob, int event, float mx, float my, char key)
/* Handles the browser */
{
int i;
SPEC *sp = ((SPEC *)(ob->spec));
switch (event)
{
case FL_DRAW:
if (partial == 0 || ob->form->doublebuf) draw_browser(ob);
else if (partial == 1) draw_browser_partial(ob,TRUE);
else if (partial == 2) draw_browser_partial(ob,FALSE);
partial = 0;
return 0;
case FL_PUSH:
eventtype = NOEVENT;
statuschanged = 0;
case FL_MOUSE:
if (eventtype == SELECTEVENT || eventtype == DESELECTEVENT)
{
if (my < ob->y) fl_set_browser_topline(ob,sp->topline+1);
else if (my > ob->y+ob->h) fl_set_browser_topline(ob,sp->topline-1);
}
if (handle_mouse(ob,mx,my)) statuschanged = 1;
if (statuschanged && ob->type == FL_MULTI_BROWSER)
{ statuschanged = 0; return 1; }
return 0;
case FL_RELEASE:
if (ob->type == FL_SELECT_BROWSER) fl_deselect_browser(ob);
return statuschanged;
case FL_FREEMEM:
for (i=1; i<=FL_BROWSER_MAXLINE; i++)
if (sp->text[i] != NULL) free(sp->text[i]);
free(ob->spec);
return 0;
}
return 0;
}
/*-----------------------------------------------*/
FL_OBJECT *fl_create_browser(int type,float x,float y,float w,float h,
const char *label)
/* Creates a browser */
{
int i;
FL_OBJECT *ob;
SPEC *sp;
ob = fl_make_object(FL_BROWSER,type,x,y,w,h,label,handle_browser);
ob->boxtype = FL_BROWSER_BOXTYPE;
ob->lcol = FL_BROWSER_LCOL;
ob->align = FL_BROWSER_ALIGN;
ob->col1 = FL_BROWSER_COL1;
ob->col2 = FL_BROWSER_COL2;
ob->spec = (int *) fl_malloc(sizeof(SPEC));
sp = ((SPEC *)(ob->spec));
sp->fontsize = FL_NORMAL_FONT;
sp->fontstyle = FL_NORMAL_STYLE;
sp->lines = 0;
sp->topline = 1;
sp->selectline = 0;
sp->specialkey = '@';
for (i=0; i <= FL_BROWSER_MAXLINE; i++) sp->text[i] = NULL;
return ob;
}
FL_OBJECT *fl_add_browser(int type, float x, float y, float w, float h,
const char *label)
/* Adds an object */
{
FL_OBJECT *ob;
ob = fl_create_browser(type,x,y,w,h,label);
fl_add_object(fl_current_form,ob);
return ob;
}
/*-----------------------------------------------*/
void fl_set_browser_topline(FL_OBJECT *ob, int line)
/* Sets the topline for the browser. */
{
SPEC *sp = ((SPEC *)(ob->spec));
if (line<1) line = 1;
if (line>sp->lines) line = sp->lines;
if (line == sp->topline) return;
sp->topline = line;
fl_redraw_object(ob);
}
/*-----------------------------------------------*/
void fl_clear_browser(FL_OBJECT *ob)
/* Clears the browser. */
{
((SPEC *)(ob->spec))->lines = 0;
((SPEC *)(ob->spec))->topline = 1;
((SPEC *)(ob->spec))->selectline = 0;
fl_redraw_object(ob);
}
void fl_add_browser_line(FL_OBJECT *ob,const char *newtext)
/* Adds a line of text to a browser */
{
insert_line(ob,((SPEC *)(ob->spec))->lines+1,newtext);
fl_redraw_object(ob);
}
void fl_addto_browser(FL_OBJECT *ob, const char *newtext)
/* Adds a line of text to a browser, and changes focus */
{
insert_line(ob,((SPEC *)(ob->spec))->lines+1,newtext);
((SPEC *)(ob->spec))->topline = ((SPEC *)(ob->spec))->lines;
fl_redraw_object(ob);
}
void fl_insert_browser_line(FL_OBJECT *ob, int linenumb, const char *newtext)
/* Inserts a line of text in a browser */
{
if (linenumb < 1 || linenumb > ((SPEC *)(ob->spec))->lines) return;
insert_line(ob,linenumb,newtext);
fl_redraw_object(ob);
}
void fl_delete_browser_line(FL_OBJECT *ob, int linenumb)
/* Deletes a line from a browser. */
{
if (linenumb < 1 || linenumb > ((SPEC *)(ob->spec))->lines) return;
delete_line(ob,linenumb);
fl_redraw_object(ob);
}
void fl_replace_browser_line(FL_OBJECT *ob, int linenumb, const char *newtext)
/* Replaces a line of text in a browser */
{
if (linenumb < 1 || linenumb > ((SPEC *)(ob->spec))->lines) return;
replace_line(ob,linenumb,newtext);
fl_redraw_object(ob);
}
const char *fl_get_browser_line(FL_OBJECT *ob, int linenumb)
/* Returns a pointer to a particular line in the browser. */
{
if (linenumb < 1 || linenumb > ((SPEC *)(ob->spec))->lines) return NULL;
return ((SPEC *)(ob->spec))->text[linenumb]->txt;
}
int fl_load_browser(FL_OBJECT *ob, char filename[])
/* Sets the browser to a particular file */
{
SPEC *sp;
FILE *fl;
char newtext[FL_BROWSER_LINELENGTH];
int c;
int i;
if (ob == NULL || ob->objclass != FL_BROWSER) return 0;
sp = ((SPEC *)(ob->spec));
fl_clear_browser(ob);
if (filename == NULL || filename[0] == NULL)
{fl_redraw_object(ob); return 1;}
/* LOAD THE FILE */
fl = fopen(filename,"r");
if (fl == NULL) return 0;
i = 0;
do
{
c = getc(fl);
if (c == NL || c == EOF)
{ newtext[i] = NULL; insert_line(ob,sp->lines+1,newtext); i = 0; }
else if (c == 9) /* Tab */
do
if (i< FL_BROWSER_LINELENGTH-1) newtext[i++] = ' ';
while ( i % 8 != 0 && i< FL_BROWSER_LINELENGTH-1);
else if (i< FL_BROWSER_LINELENGTH-1)
newtext[i++] = c;
} while (c != EOF);
fclose(fl);
fl_redraw_object(ob);
return 1;
}
int fl_get_browser_maxline(FL_OBJECT *ob)
/* Returns the number of lines in the browser. */
{ return ((SPEC *)(ob->spec))->lines; }
/*-----------------------------------------------*/
void fl_select_browser_line(FL_OBJECT *ob, int line)
/* Selects a line in the browser. */
{
SPEC *sp = ((SPEC *)(ob->spec));
if (line < 1 || line > sp->lines) return;
if (ob->type != FL_MULTI_BROWSER && sp->selectline >0)
sp->text[sp->selectline]->selected = 0;
sp->text[line]->selected = 1;
sp->selectline = line;
fl_redraw_object(ob);
}
void fl_deselect_browser_line(FL_OBJECT *ob, int line)
/* Deselects a line in the browser. */
{
SPEC *sp = ((SPEC *)(ob->spec));
if (line < 1 || line > sp->lines) return;
sp->text[line]->selected = 0;
if (ob->type != FL_MULTI_BROWSER && sp->selectline == line)
sp->selectline = 0;
else if (ob->type == FL_MULTI_BROWSER)
sp->selectline = -line;
fl_redraw_object(ob);
}
void fl_deselect_browser(FL_OBJECT *ob)
/* Deselects all lines in the browser. */
{
int i;
for (i=1; i<= ((SPEC *)(ob->spec))->lines; i++)
((SPEC *)(ob->spec))->text[i]->selected = 0;
fl_redraw_object(ob);
}
int fl_isselected_browser_line(FL_OBJECT *ob, int line)
/* Returns whether a line in the browser is selected. */
{
if (line < 1 || line > ((SPEC *)(ob->spec))->lines) return 0;
return ((SPEC *)(ob->spec))->text[line]->selected;
}
int fl_get_browser(FL_OBJECT *ob)
/* Returns the last selection in the browser. */
{ return ((SPEC *)(ob->spec))->selectline; }
/*-----------------------------------------------*/
void fl_set_browser_fontsize(FL_OBJECT *ob, float size)
/* Sets the font size inside the browser. */
{
((SPEC *)(ob->spec))->fontsize = size;
fl_redraw_object(ob);
}
/*TCZ*/
int fl_get_browser_topline(FL_OBJECT *ob)
{
return ((SPEC *)ob->spec)->topline;
}
void fl_set_browser_fontstyle(FL_OBJECT *ob, int style)
/* Sets the font style inside the browser. */
{
((SPEC *)(ob->spec))->fontstyle = style;
fl_redraw_object(ob);
}
void fl_set_browser_specialkey(FL_OBJECT *ob, char specialkey)
/* Sets the escape key used in the text */
{
((SPEC *)(ob->spec))->specialkey = specialkey;
fl_redraw_object(ob);
}